import mongoose from 'mongoose'
import bcrypt from 'bcryptjs'
const Schema=mongoose.Schema
const SALT_WORK_FACTOR=10
const MAX_LOGIN_ATTEMPTS=5
const LOCK_TIME=2*60*60*1000
const userSchema=new Schema({
    username:{
        unique:true,
        required:true,
        type:String
    },
    email:{
        unique:true,
        required:true,
        type:String
    },
    password:{
        unique:true,
        type:String
    },
    role:{
        type:String,
        ddefault:'user'
    },
    lockUntil:Number,
    meta:{
        createdAt:{
            type:Date,
            ddefault:Date.now()
        },
        updatedAt:{
            type:Date,
            ddefault:Date.now()
        }
    }

})

userSchema.virtual('isLocked').get(function(){
    return !!(this.lockUntil&&this.lockUntil>Date.now())
})
userSchema.pre('save',function(next){
    if (this.isNew) {
        this.meta.createdAt = this.meta.updatedAt = Date.now()
      } else {
        this.meta.updatedAt = Date.now()
      }
    
      next()
})

userSchema.pre('save',function(next){
    if(!this.isModified('password'))return next()

    bcrypt.genSalt(SALT_WORK_FACTOR,(error,salt)=>{
        if(error)return next(error)

        bcrypt.hash(this.password,salt,(error,hash)=>{
            if(error)return next(error)
            this.password=hash
            next()
        })
    })
})
userSchema.methods={
    comparePassword:(_password,password)=>{
        return new Promise((resolve,reject)=>{
            bcrypt.compare(_password,password,(error,isMath)=>{
                if(!error)resolve(isMath)
                else reject (error)
            })
        })
    },
    incLoginAttepts:(user)=>{
        return new Promise((resolve,reject)=>{
            if(this.lockUntil&&this.lockUntil<Date.now()){
                this.update({
                    $set:{
                        incLoginAttepts:1
                    },
                    $unset:{
                        lockUntil:1
                    }
                },(error)=>{
                    if(!error)resolve(true)
                    else reject(error)
                })
            }else{
                let updates={
                    $inc:{
                        incLoginAttepts:1
                    }
                }
                if(this.incLoginAttepts+1>=MAX_LOGIN_ATTEMPTS&&!this.isLocked){
                    updates.$set={
                        lockUntil:Date.now()+LOCK_TIME
                    }

                }
                this.update(updates,err=>{
                    if(!err)resolve(true)
                    else reject(err)
                })
            }
        })
    }
}
mongoose.model('User',userSchema)